﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace DBManager
{
    public class DBManager
    {
        private CalcDataClassesDataContext m_db = null;
        static DBManager instance = null;

        static volatile Mutex m_mutex = new Mutex(false);

        private bool isLock = false;

        static public string connectionString;

        DBManager()
        {
            m_db = new CalcDataClassesDataContext();
        }

        public static DBManager Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new DBManager();
                }

                return instance;
            }
        }

        public void mutexlock()
        {
           // m_mutex.WaitOne(5000,false);
            if (isLock)
            {
                while (isLock)
                {

                    System.Threading.Thread.Sleep(100);
                }
            }

            isLock = true;
        }

        public void mutexUnlock()
        {
           // m_mutex.ReleaseMutex();
            isLock = false;
        }

        public List<Customer> GetCustomerList()
        {
            m_db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, m_db.Customers);
            return m_db.Customers.Where(d => d.ListedCustomer == 1).ToList<Customer>();
        }

        public Customer GetCustomer(string customerId)
        {
            Customer cust =  m_db.Customers.Single<Customer>(d => d.CustomerID == customerId);

            m_db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, cust);

            return cust;

        }

        public List<Column> GetColumns(string grpId, string calcId)
        {
            return m_db.Columns.Where(d => d.GroupID == grpId && d.CalculationID == calcId).ToList<Column>();
        }

        public List<OutputColumn> GetOutputColumns(string calcId, string fid)
        {
            return m_db.OutputColumns.Where(d => d.CalculationID == calcId && d.FieldID == fid).ToList<OutputColumn>();
        }

        public void refreshInputGroupS()
        {
        }

        public void refreshOrderControl(OrderControl orderControl)
        {
            m_db.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, orderControl);
        }

        public void refreshOutputs()
        {
            m_db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, m_db.OutputValues);
            m_db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, m_db.ChartOutputs);
        }


        public List<InputDesignGroup> GetInputDesignGroups(string calculationsId)
        {
            return m_db.InputDesignGroups.Where(d => d.CalculationID == calculationsId).OrderBy(d => d.ID).ToList<InputDesignGroup>();
        }

        public List<OutputDesignGroup> GetOutputDesignGroups(string calculationsId)
        {
            return m_db.OutputDesignGroups.Where(d => d.CalculationID == calculationsId).OrderBy(d => d.ID).ToList<OutputDesignGroup>();
        }

        public Calculation GetCalculation(string calculationId)
        {
            Calculation calc = m_db.Calculations.Single<Calculation>(d => d.CalculationID == calculationId);

            if (calc != null)
            {
                m_db.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, calc);
            }

            return calc;
        }

        public List<OrderControl> GetOrderControlList(string calculationId, string userId)
        {
            m_db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, m_db.OrderControls);
            List<OrderControl> list = m_db.OrderControls.Where<OrderControl>(d => d.Saved == true && d.CalculationID == calculationId && d.UserID == userId).OrderByDescending(d => d.ID).ToList();

            return list;
        }

        public OrderControl GetLatestOrderControl(string calculationId, string userId)
        {
            return m_db.OrderControls.Where<OrderControl>(d => d.Saved == true && d.CalculationID == calculationId && d.UserID == userId).OrderByDescending(d => d.ID).FirstOrDefault();
        }

        public OrderControl GetOrderControl(string orderId)
        {
            return m_db.OrderControls.SingleOrDefault<OrderControl>(d => d.ID == Convert.ToInt32(orderId));
        }

        public ChartDesign GetChartDesign(string calculationId)
        {
            return m_db.ChartDesigns.SingleOrDefault<ChartDesign>(d => d.CalculationID == calculationId);
        }

        public List<InputDesign> GetInputDesignList(string calculationId, string groupId)
        {
            return m_db.InputDesigns.Where(d => d.GroupID == groupId && d.CalculationID == calculationId).OrderBy(d => d.ID).ToList<InputDesign>();
        }

        public List<OutputDesign> GetOutputDesignList(string calculationId, string groupId)
        {
           
            List<OutputDesign> out_list =  m_db.OutputDesigns.Where(d => d.GroupID == groupId && d.CalculationID == calculationId).ToList<OutputDesign>();
            m_db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, out_list);

            return out_list;
        }

        public List<OutputValue> GetOutputValuesList(string calcId, string fid, string orderId)
        {
            return m_db.OutputValues.Where(d => d.CalculationID == calcId && d.FieldID == fid && d.OrderID == orderId).ToList<OutputValue>();
        }

        public OutputColumn GetOutputColumn(string calcId, string FieldId, int col)
        {
            List<OutputColumn> list = m_db.OutputColumns.Where(d => d.CalculationID == calcId && d.FieldID == FieldId && d.ColumnNu == col).ToList();

            if (list.Count == 0)
                return null;

            m_db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, list);

            return list[0];
        }

        public List<ChartOutput> GetChartOutputList(string calcId, string fid, string orderId)
        {
            return m_db.ChartOutputs.Where(d => d.CalculationID == calcId && d.FieldID == fid && d.OrderID == orderId).ToList<ChartOutput>();
        }

        public List<InputDesignList> GetInputListItemDesign(string calculationId, string listId)
        {
            return m_db.InputDesignLists.Where(d => d.CalculationID == calculationId && d.ListID == listId).ToList<InputDesignList>();
        }

        public bool AddUser(User user)
        {
            m_db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, m_db.Users);

            if (m_db.Users.SingleOrDefault(d => d.UserName == user.UserName) != null)
            {
                return false;
            }

            m_db.Users.InsertOnSubmit(user);
            Save();

            return true;
        }

        public void Add(InputValue inputValue)
        {
            m_db.InputValues.InsertOnSubmit(inputValue);

        }

        public void Add(OrderControl orderControl)
        {
            m_db.OrderControls.InsertOnSubmit(orderControl);
        }

        public User GetUser(string userName, string password)
        {
            m_db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, m_db.Users);
            return m_db.Users.SingleOrDefault(d => d.UserName == userName && d.Code == password);
        }

        //Persistence
        public void Save()
        {
            m_db.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict);
        }


        public User GetUser(string userName)
        {
            User user = m_db.Users.SingleOrDefault(d => d.UserName == userName);

            m_db.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, user);

            return user;

        }

        public Access GetAcesss(string userId, string CalcId)
        {
            Access access = m_db.Accesses.SingleOrDefault(d => d.CalculationID == CalcId && d.UserID == userId);

            if(access != null)
                m_db.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, access);

            return access;
        }

        public List<Access> GetAcesss(string userId)
        {
            //Access access = m_db.Accesses.SingleOrDefault(d => d.CalculationID == CalcId && d.UserID == userId);

            List<Access> list =  m_db.Accesses.Where(d => d.UserID.ToLower() == userId.ToLower()).ToList<Access>();

            m_db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, list);

            return list;
        }

        public Point GetPoint(string userId, string calcId)
        {
            Point point = m_db.Points.SingleOrDefault(d => d.UserID == userId && d.CalculationID == calcId);

            if (point != null)
                m_db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, point);

            return point;
        }


        public dynamic GetStandardCalculation()
        {
            return m_db.Calculations.Where(d => d.CustomerID == null).ToList<Calculation>();
        }


        public InputDesign GetInputDesign(string fieldId, string calculationId)
        {
            return m_db.InputDesigns.SingleOrDefault(d => d.FieldID == fieldId && d.CalculationID == calculationId);
        }
    }
}